/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.message;

import com.jnetx.javax.sip.address.AddressFactoryImpl;
import com.jnetx.javax.sip.header.*;
import com.jnetx.javax.sip.util.ByteArrayUtil;
import com.jnetx.javax.sip.util.ByteData;
import com.jnetx.javax.sip.util.CharacterTree;
import com.jnetx.javax.sip.util.KeywordChecker;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.sip.header.*;
import java.text.ParseException;

/**
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class SIPRequestParser extends SIPMessageParser {
    private static final Log logger = LogFactory.getLog(SIPRequestParser.class);

    private static final KeywordChecker availableMethods = new KeywordChecker(
            SIPRequest.ACK, SIPRequest.BYE, SIPRequest.CANCEL, SIPRequest.INFO, SIPRequest.INVITE,
            SIPRequest.MESSAGE, SIPRequest.NOTIFY, SIPRequest.OPTIONS, SIPRequest.PRACK,
            SIPRequest.PUBLISH, SIPRequest.REFER, SIPRequest.REGISTER, SIPRequest.SUBSCRIBE, SIPRequest.UPDATE);

    private SIPRequestParser() {
    }

    static SIPRequest parseRequest(byte[] requestData) throws ParseException {
        return parseRequest(requestData, null);
    }

    static SIPRequest parseRequest(byte[] requestData, SIPRequest request) throws ParseException {
        if (request == null) request = new SIPRequest();
        //Method
        final int methodEnd = ByteArrayUtil.firstOccurence(requestData, ' ');
        if (methodEnd == -1)
            fail("Cannot parse SIP method!", 0);
        final String method = new String(requestData, 0, methodEnd);
        checkMethod(method);
        request.setMethod(method);
        //Request URI
        final int requestURIStart = ByteArrayUtil.firstMissing(requestData, ' ', methodEnd + 1);
        final int requestURIStop = ByteArrayUtil.firstOccurence(requestData, ' ', requestURIStart + 1);
        if (requestURIStart == -1 || requestURIStop == -1)
            fail("Cannot parse request URI!", requestURIStart);
        final String requestURIStr = new String(requestData, requestURIStart, requestURIStop - requestURIStart);
        request.setRequestURI(AddressFactoryImpl.createURILazily(requestURIStr));
        //SIP version
        final int startOfSIPVersion = ByteArrayUtil.firstMissing(requestData, ' ', requestURIStop + 1);
        final int endOfRequestLine = ByteArrayUtil.firstEndOfLine(requestData, startOfSIPVersion);
        final String sipVersion = new String(requestData, startOfSIPVersion, endOfRequestLine - startOfSIPVersion);
        request.setSIPVersion(sipVersion);
        //Parse headers
        final int startOfHeaders = endOfRequestLine + 2;
        final int startOfBody = parseHeaders(requestData, request, startOfHeaders);
        //Parse body
        //todo
        return request;
    }

    private static void checkMethod(String method) throws ParseException {
        if (method == null || !availableMethods.checkKeyword(method))
            throw new ParseException("Unknown method: " + method, 0);
    }
}
/*
 * $Log$
 */